#include "internal.h"

extern struct gatts_char chars[];

/**
 * @brief nfc扫描
 * @return tag信息发生变化返回true，否则返回false
 */
static bool nfc_scan(uint8_t nfc_id_buf[ID_LEN])
{
	static gatts_err_t ret;
	static rc522_err_t r;

	static struct rc522_tag tag1 = { 0 };
	static struct rc522_tag tag2 = { 0 };
	static struct rc522_tag *newtag = &tag1;
	static struct rc522_tag *oldtag = &tag2;
	static struct rc522_tag *tmptag;

	// printf("\e[1;1H\e[2J");
	r = rc522_scan(newtag);
	if (r == RC522_NOTAG)
		r = rc522_scan(newtag);

	if (rc522_tag_eq(newtag, oldtag))
		return false;

	printf("scan state: %d\n", r);

	printf("\nsn: %02X%02X%02X%02X\n", newtag->tag_serial_num[0],
	       newtag->tag_serial_num[1], newtag->tag_serial_num[2],
	       newtag->tag_serial_num[3]);
	printf("tag type: %02X%02X\n", newtag->tag_type[0],
	       newtag->tag_type[1]);

	memcpy(&nfc_id_buf[0], &newtag->tag_type, 2);
	memcpy(&nfc_id_buf[2], &newtag->tag_serial_num, 4);

	ret = gatts_set_value(&chars[NFC_ID].uuid, nfc_id_buf, ID_LEN);
	if (ret != GATTS_OK)
		return false;

	ret = gatts_indicate(&chars[NFC_ID].uuid);
	if (ret != GATTS_OK)
		return false;

	// new，old tag交换
	tmptag = newtag;
	newtag = oldtag;
	oldtag = tmptag;

	return true;
}

/**
 * @brief nfc读取
 * @param key_A 密钥A
 * @param addr 块地址
 * @return 成功读取返回true，否则返回false
 */
static bool nfc_read(uint8_t nfc_data_buf[DATA_LEN], uint8_t nfc_id_buf[ID_LEN],
		     const uint8_t *key_A, uint8_t addr)
{
	static gatts_err_t ret;
	static rc522_err_t r;

	static struct rc522_tag tag = { 0 };
	r = rc522_scan(&tag);
	if (r != RC522_OK)
		return false;

	r = rc522_read(&tag, key_A, addr, nfc_data_buf);
	if (r != RC522_OK)
		return false;

	memcpy(&nfc_id_buf[0], &tag.tag_type, 2);
	memcpy(&nfc_id_buf[2], &tag.tag_serial_num, 4);

	ret = gatts_set_value(&chars[NFC_ID].uuid, nfc_id_buf, ID_LEN);
	if (ret != GATTS_OK)
		return false;

	ret = gatts_set_value(&chars[NFC_DATA].uuid, nfc_data_buf, DATA_LEN);
	if (ret != GATTS_OK)
		return false;

	ret = gatts_indicate(&chars[NFC_ID].uuid);
	if (ret != GATTS_OK)
		return false;

	printf("read state: %d\n", r);

	for (int i = 0; i < DATA_LEN; i++) {
		if (i % 4 == 0)
			puts("");
		printf("%02x ", nfc_data_buf[i]);
	}
	puts("");
	return true;
}

/**
 * @brief nfc写入
 * @param key_A 密钥A
 * @param addr 块地址
 * @return 成功写入返回true，否则返回false
 */
static bool nfc_write(uint8_t nfc_data_buf[DATA_LEN],
		      uint8_t nfc_id_buf[ID_LEN], const uint8_t *key_A,
		      uint8_t addr)
{
	static gatts_err_t ret;
	static rc522_err_t r;

	static struct rc522_tag tag = { 0 };
	r = rc522_scan(&tag);
	if (r != RC522_OK)
		return false;
	printf("debug : %d\n", 1);

	ret = gatts_get_value(&chars[NFC_DATA].uuid, nfc_data_buf, NULL,
			      DATA_LEN);
	r = rc522_write(&tag, key_A, addr, nfc_data_buf);
	if (r != RC522_OK) {
		printf("w debug : %u\n", r);
		return false;
	}

	printf("debug : %d\n", 2);

	memcpy(&nfc_id_buf[0], &tag.tag_type, 2);
	memcpy(&nfc_id_buf[2], &tag.tag_serial_num, 4);

	ret = gatts_set_value(&chars[NFC_ID].uuid, nfc_id_buf, ID_LEN);
	if (ret != GATTS_OK)
		return false;

	printf("debug : %d\n", 3);

	ret = gatts_indicate(&chars[NFC_ID].uuid);
	if (ret != GATTS_OK)
		return false;

	printf("write state: %d\n", r);

	for (int i = 0; i < DATA_LEN; i++) {
		if (i % 4 == 0)
			puts("");
		printf("%02x ", nfc_data_buf[i]);
	}
	puts("");
	return true;
}

void rc522_task(void *arg)
{
	rc522_err_t r;

	static uint8_t nfc_conf_buf[CONF_LEN] = { 0 };
	static uint8_t nfc_id_buf[ID_LEN] = { 0 };
	static uint8_t nfc_data_buf[DATA_LEN] = { 0 };
	static uint8_t nfc_stat_buf[STAT_LEN] = { 0 };

	gatts_get_value(&chars[NFC_CONF].uuid, nfc_conf_buf, NULL, CONF_LEN);

	uint8_t *key_A = &nfc_conf_buf[2];

	while (1) // 任务都是一个无限循环，不能返回
	{
		gatts_get_value(&chars[NFC_CONF].uuid, nfc_conf_buf, NULL,
				CONF_LEN);

		// 判断使能位
		if (!get_nfc_enabled(nfc_conf_buf)) {
			vTaskDelay(1000 / portTICK_PERIOD_MS); // 1s
			continue;
		}

		uint8_t nfc_mode = get_nfc_mode(nfc_conf_buf);
		// printf("task suspended: %u\n", get_nfc_suspended(nfc_conf_buf));

		if (nfc_mode == 0) {
			nfc_scan(nfc_id_buf);
		}

		if (get_nfc_suspended(nfc_conf_buf))
			goto end;

		if (nfc_mode == 1) {
			if (!nfc_write(nfc_data_buf, nfc_id_buf, key_A, 4))
				goto end;
			set_nfc_suspend(nfc_conf_buf);
		}

		if (nfc_mode == 2) {
			if (!nfc_read(nfc_data_buf, nfc_id_buf, key_A, 4))
				goto end;
			set_nfc_suspend(nfc_conf_buf);
		}
end:
		gatts_set_value(&chars[NFC_CONF].uuid, nfc_conf_buf, CONF_LEN);

		vTaskDelay(200 / portTICK_PERIOD_MS); // 100ms
	}
}